package com.arrcen.medicen.core.match.service.impl;

import com.arrcen.medicen.core.match.helper.OracleHelper;
import com.arrcen.medicen.core.match.mapper.MapperHelper;
import com.arrcen.medicen.core.match.model.dto.*;
import com.arrcen.medicen.core.match.model.entity.SyncTableEntity;
import com.arrcen.medicen.core.match.model.entity.SyncTableFieldEntity;
import com.arrcen.medicen.core.match.service.SyncTable;

import com.arrcen.medicen.core.match.service.*;
import com.arrcen.medicen.core.match.utlity.LogHelper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SyncTableImp implements SyncTable {

    @Resource
    LogHelper logHelper;

    //连接数据库的参数
    @Value("${driver-class-name}")
    String driver;

    @Value("${source.url}")
    String url ;
    @Value("${source.username}")
    String username;
    @Value("${source.password}")
    String passwd ;

    @Value("${target.url}")
    String targetUrl ;
    @Value("${target.username}")
    String targetUsername;
    @Value("${target.password}")
    String targetPasswd ;


    @Resource
    SyncTableFieldService syncTableFieldService;

    @Resource
    SyncTableService syncTableService;



    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result saveSyncConfig(DtoSyncTable inEnt) {
        Result result=new Result();
        String cen_table_name = inEnt.cenTableName;
        String tmp_table_name = inEnt.tmpTableName;
        SyncTableEntity single = syncTableService.getOne(SyncTableEntity.class, x -> x.cenTableName == cen_table_name && x.tmpTableName == tmp_table_name);
        int opNum=0;
        if (single != null) {
            opNum=syncTableFieldService.getBaseMapper().delete(
                    Wrappers.lambdaQuery(SyncTableFieldEntity.class)
                            .eq(SyncTableFieldEntity::getSyncTableId,single.syncTableId)
            );
            SyncTableEntity tableEntity=new SyncTableEntity();
            tableEntity.setName(inEnt.getName());
            tableEntity.setPageSize(inEnt.getPageSize());
            tableEntity.setApiUrl(inEnt.getApiUrl());

            syncTableService.update(tableEntity,
                    Wrappers.lambdaUpdate(SyncTableEntity.class)
                            .eq(SyncTableEntity::getSyncTableId,single.syncTableId)
            );
        }else {
            single = new SyncTableEntity();
            single.setName(inEnt.getName());
            single.setApiUrl(inEnt.getApiUrl());
            single.setPageSize(inEnt.getPageSize());
            single.setCenTableName(inEnt.getCenTableName());
            single.setTmpTableName(inEnt.getTmpTableName());
            single.setSyncTableId(syncTableService.getIncreasingId(SyncTableEntity.class));
            single.setStatus(1);
            opNum = syncTableService.getBaseMapper().insert(single);
        }

        if (opNum > 0) {
            for (DtoSyncTableField temp : inEnt.fields) {
                SyncTableFieldEntity syncTableFieldEntity = new SyncTableFieldEntity();
                syncTableFieldEntity.setSyncTableFieldId(syncTableFieldService.getIncreasingId(SyncTableFieldEntity.class));
                syncTableFieldEntity.setSyncTableId(single.getSyncTableId());
                syncTableFieldEntity.setApiFieldName(temp.getApiFieldName());
                syncTableFieldEntity.setCenFieldName(temp.getCenFieldName());
                syncTableFieldEntity.setTmpFieldName(temp.getTmpFieldName());
                syncTableFieldEntity.setOpType(temp.getOpType());
                syncTableFieldService.save(syncTableFieldEntity);
            }
        }
        result.setStatus(1);
        return result;
    }

    @Override
    @Transactional
    public Result delete(int key) {
        Result resul=new Result();
        syncTableFieldService.delete(SyncTableFieldEntity.class,x->x.syncTableId==key);
        int opNum=syncTableService.delete(SyncTableEntity.class,x->x.syncTableId==key);
        resul.setStatus(1);
        return resul;
    }

    @Override
    public Result updateStatus(int key, int status) {
        UpdateWrapper<SyncTableEntity> updateWrapper=new UpdateWrapper<>(new SyncTableEntity());
        updateWrapper.lambda()
                .eq(SyncTableEntity::getSyncTableId,key)
                .set(SyncTableEntity::getStatus,status)
        ;

        boolean update = syncTableService.update(updateWrapper);
        Result resul=new Result();
        resul.setStatus(update);
        return resul;
    }

    @Override
    public IPage<SyncTableEntity> getAll(DtoPage dtoPage) {
        ResultObj<SyncTableEntity> resultObj=new ResultObj<>();
        Page<SyncTableEntity> page = syncTableService.page(
                new Page<>(dtoPage.getPage(), dtoPage.getRows()),
                Wrappers.lambdaQuery(SyncTableEntity.class)
        );
        return page;
    }

    @Override
    public DtoSyncTable getDetail(int key) {
        SyncTableEntity single = syncTableService.getOne(SyncTableEntity.class, x -> x.syncTableId==key);
        DtoSyncTable dtoSyncTable = new DtoSyncTable();
        if(single!=null) {
            List<DtoSyncTableField> listField = new ArrayList<>();
            dtoSyncTable.setApiUrl(single.getApiUrl());
            dtoSyncTable.setCenTableName(single.getCenTableName());
            dtoSyncTable.setName(single.getName());
            dtoSyncTable.setTmpTableName(single.getTmpTableName());
            dtoSyncTable.setPageSize(single.getPageSize());
            List<SyncTableFieldEntity> allField = syncTableFieldService.list(SyncTableFieldEntity.class, x->x.syncTableId==key, 1, 100, null);
            for (int i = 0; i <allField.size() ; i++) {
                SyncTableFieldEntity item=allField.get(i);
                DtoSyncTableField field = new DtoSyncTableField();
                field.setApiFieldName(item.getApiFieldName());
                field.setCenFieldName(item.getCenFieldName());
                field.setOpType(item.getOpType());
                field.setTmpFieldName(item.getTmpFieldName());
                listField.add(field);
            }

            dtoSyncTable.setFields(listField);
        }
        return dtoSyncTable;
    }


    @Override
    public List<String> getTargetTable() {
        return getTableName(driver,targetUrl,targetUsername,targetPasswd);
    }

    @Override
    public List<String> getSourceTable() {
        return getTableName(driver,url,username,passwd);
    }
    @Override
    public List<String> getTargetField(String tableName) {
        return getTableField(driver,targetUrl,targetUsername,targetPasswd,tableName);
    }

    @Override
    public List<String> getSourceField(String tableName) {
        return getTableField(driver,url,username,passwd,tableName);
    }



    public List<String> getTableName( String _driver,
                                           String _url ,
                                           String _username ,
                                           String _passwd) {
        String sql=String.format("select table_name from user_tables where TABLESPACE_NAME is not null and  user='%s' ",_username.toUpperCase());
        OracleHelper.init(_driver,_url,_username,_passwd);
        ResultSet rs = OracleHelper.executeQuery(sql, null);
        List<String> resultObj=new ArrayList<>();
        try {
            while(rs.next()){
                String name = rs.getString(1);
                resultObj.add(name);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return resultObj;
    }


    public List<String> getTableField( String _driver,
                                           String _url ,
                                           String _username ,
                                           String _passwd,
                                            String tableName){

        String sql=String.format("SELECT column_name FROM all_tab_cols WHERE table_name ='%s' ",tableName.toUpperCase());
        OracleHelper.init(_driver,_url,_username,_passwd);
        ResultSet rs = OracleHelper.executeQuery(sql, null);
        List<String> resultObj=new ArrayList<>();
        try {
            while(rs.next()){
                String name = rs.getString(1);
                resultObj.add(name);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return resultObj;
    }

    @Override
    public ResultHashMap saveData(DtoSaveTable inData) {
        ResultHashMap resultHashMap = new ResultHashMap(true);
        if(inData.getSaveMapList().size()<1)return  resultHashMap;

        logHelper.info(SyncTableImp.class,"开始保存数据");

        List<Integer> increasingIdList = syncTableService.getIncreasingIdList(inData.tableName, inData.getSaveMapList().size());
        logHelper.info(SyncTableImp.class,"管理批量ID");

        for (int i = 0; i <increasingIdList.size() ; i++) {

            inData.getSaveMapList().get(i).put("系统序号",increasingIdList.get(i).toString());
        }



        List<String> valuesList=new ArrayList<>();
        String fieldStr = String.join(",", inData.getSaveMapList().get(0).keySet().stream().map(x -> x).collect(Collectors.toList()));
        for (HashMap<String,String> item:inData.getSaveMapList()
             ) {
            List<String> collect = item.values().stream().map(x -> x).collect(Collectors.toList());
            valuesList.add(String.format("INSERT INTO %s ( %s ) VALUES ('%s')",inData.tableName,fieldStr,String.join("','",collect)));
        }
        OracleHelper.init(driver,targetUrl,targetUsername,targetPasswd);
        if(OracleHelper.supportBatch()){
            OracleHelper.insertList(valuesList);
        }
        logHelper.info(SyncTableImp.class,"批量插入数据结束");


        return resultHashMap;
    }
}
